package com.bruce.spring.http.service.cgroup;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * Cgroup v2 容器CPU使用率提供者
 * 仅通过 user_usec + system_usec 计算总CPU耗时
 */
public abstract class CgroupV2BaseProvider implements CpuUsageProvider {
    // Cgroup v2 固定路径
    private static final String CPU_PATH = "/sys/fs/cgroup/";
    private static final String CPU_MAX = "cpu.max";
    private static final String CPU_STAT = "cpu.stat";

    // 关键字常量（仅保留用户态和内核态耗时）
    protected static final String USER_USEC = "user_usec";
    protected static final String SYSTEM_USEC = "system_usec";

    protected static final char SPACE = ' ';

    // 成员变量
    protected final String cpuStatPath;
    protected final String cpuMaxPath;

    private final double allocatableCores;

    public CgroupV2BaseProvider() throws IOException {
        this.cpuStatPath = CPU_PATH + CPU_STAT;
        this.cpuMaxPath = CPU_PATH + CPU_MAX;

        // 验证文件存在性
        validateFiles();
        // 初始化可分配核心数（仅执行一次）
        this.allocatableCores = calculateAllocatableCores();
    }

    /**
     * 验证必要文件是否存在
     */
    private void validateFiles() throws IOException {
        if (!Files.exists(Paths.get(cpuStatPath))) {
            throw new IOException("cgroup v2文件不存在: " + cpuStatPath);
        }
        if (!Files.exists(Paths.get(cpuMaxPath))) {
            throw new IOException("cgroup v2文件不存在: " + cpuMaxPath);
        }
    }

    /**
     * 计算可分配的CPU核心数（基于cpu.max）
     */
    private double calculateAllocatableCores() throws IOException {
        // 读取cpu.max单行内容（高效单行处理）
        String content = new String(Files.readAllBytes(Paths.get(cpuMaxPath))).trim();
        if (content.isEmpty()) {
            throw new IOException("cpu.max文件内容为空");
        }

        // 无限制情况（quota为max）
        if (content.startsWith("max")) {
            return Runtime.getRuntime().availableProcessors();
        }

        // 分割配额(quota)和周期(period)
        int spaceIndex = content.indexOf(SPACE);
        if (spaceIndex == -1) {
            throw new IOException("cpu.max格式错误，应为'quota period': " + content);
        }

        String quotaStr = content.substring(0, spaceIndex);
        String periodStr = content.substring(spaceIndex + 1).trim();

        // 计算核心数：quota / period
        long quota = Long.parseLong(quotaStr);
        long period = Long.parseLong(periodStr);
        return period == 0 ? 1.0 : (double) quota / period;
    }


    @Override
    public double getAllocatableCores() {
        return allocatableCores;
    }


}